package org.cli.admin.command;

import java.io.IOException;
import java.net.URL;
import java.util.Map;
import java.util.Set;

import org.scannotation.AnnotationDB;
import org.scannotation.ClasspathUrlFinder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.inject.AbstractModule;
import com.google.inject.multibindings.Multibinder;

public class CommandModule extends AbstractModule {
	private static final Logger logger = LoggerFactory.getLogger(CommandModule.class);

	@Override
	protected void configure() {
		logger.info("Installing base commands");

		bind(CommandManager.class);

		URL[] urls = ClasspathUrlFinder.findClassPaths();
		try {
			AnnotationDB db = new AnnotationDB();
			db.setScanClassAnnotations(true);
			db.scanArchives(urls);

			Map<String, Set<String>> annotationIndex = db.getAnnotationIndex();

			Multibinder<ICommand> multibinder = Multibinder.newSetBinder(binder(), ICommand.class);

			Set<String> commandClassNames = annotationIndex.get(Command.class.getName());

			for (String commandClassName : commandClassNames) {

				try {
					Class<?> aClass = Class.forName(commandClassName);
					if (ICommand.class.isAssignableFrom(aClass)) {

						@SuppressWarnings("unchecked")
						Class<? extends ICommand> commandClass = (Class<? extends ICommand>) aClass;

						if (commandClass.getAnnotation(Command.class).global()) {
							multibinder.addBinding().to(commandClass);
							bind(commandClass);

							logger.info(commandClass.getAnnotation(Command.class).name() + " command installed");
						}
					}
				} catch (ClassNotFoundException e) {
					logger.info("Could not find command class:" + commandClassName);
				}
			}

		} catch (IOException e) {
			this.addError("Exception when finding annotated commands", e);
		}

	}

}
